using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using WebapiTemplate.Domain.Entity;
using WebapiTemplate.Application.Utils;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Controllers;
using WebapiTemplate.Application.Common.Interface;


/// <summary>
/// 审计日志具体实现类，需要在Program.cs类中启用
/// </summary>
namespace WebapiTemplate.Infrastructure.Filter
{
    public class AuditLogActionFilter : IAsyncActionFilter//继承Mvc自带的Action过滤器
    {
        //定义存放审计日志的数据库表实例字段
        private readonly IRepository<AuditLog> _auditLog;



        //依赖注入得到字段的真正表实例
        public AuditLogActionFilter(IRepository<AuditLog> auditLog)
        {
            _auditLog = auditLog;
        }




        //实现过滤器IAsyncActionFilter接口的方法
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //接口Type
            var type = (context.ActionDescriptor as ControllerActionDescriptor)?.ControllerTypeInfo.AsType();
            //方法信息
            var method = (context.ActionDescriptor as ControllerActionDescriptor)?.MethodInfo;
            //方法参数
            var arguments = context.ActionArguments;
            //开始计时
            var stopwatch = Stopwatch.StartNew();



            //创建AuditLog表，并添加日志数据
            var auditInfo = new AuditLog
            {
                UserInfo = "第一个审计人",
                ServiceName = type != null ? type.FullName : "",//来自于上面的接口type
                MethodName = method?.Name,
                Parameters = JsonHelper.toJsonObject(arguments),//Json化方法的请求参数
                ExecutionTime = DateTime.Now,
                ClientName = context.HttpContext.Connection.LocalPort.ToString(),
                ClientIpAddress = context.HttpContext.Connection?.RemoteIpAddress?.ToString(),
                BrowserInfo = context.HttpContext.Request.Headers["User-Agent"],
                //CustomData 这个字段暂时不填数据
            };




            //定义一个方法执行结果所有信息的类型对象(这个对象不仅仅只是Action的返回值,还有执行过程中的异常等等一系列信息)
            ActionExecutedContext? result = null;
            try
            {
                result = await next();
                //执行过程因为代码问题产生的异常
                if (result.Exception != null && !result.ExceptionHandled)
                {
                    auditInfo.Exception = result.Exception.ToString();

                }
            }
            //系统异常
            catch (Exception ex)
            {
                auditInfo.Exception = ex.ToString();
                throw;
            }
            finally
            {
                 //方法结束,停止计时
                auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);//消耗了多少时间


                //为方法的返回值ReturnValue属性赋值
                if (result != null)
                {
                    switch (result.Result)
                    {
                        case ObjectResult objectResult:
                            auditInfo.ReturnValue = objectResult.Value==null ? "" :JsonHelper.toJsonObject(objectResult.Value);
                            break;

                        case JsonResult jsonResult:
                            auditInfo.ReturnValue = jsonResult.Value==null ? "" :JsonHelper.toJsonObject(jsonResult.Value);
                            break;

                        case ContentResult contentResult:
                            auditInfo.ReturnValue = contentResult.Content;
                            break;
                    }
                }


                //在控制台打印，确定已走此步
                Console.WriteLine("auditInfo".ToString());


                //保存审计日志
                await _auditLog.AddAsync(auditInfo);
            }
        }

    }
}